home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 003 / roff / tpr1.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  14KB  |  790 lines

  1. #include    "tpr.h"
  2.  
  3. /*
  4. **    expand - pushback macro definition onto input
  5. */
  6. expand(macnum)
  7.     short macnum;{
  8.     register struct linelink *lp;
  9.     
  10.     for(lp = macros[macnum].macend; lp != NULL; lp = lp->lastline)
  11.         pushback(lp->lineptr);
  12. }
  13.  
  14. /*
  15. **    getmac - collect macro
  16. */
  17. getmac(buf,file)
  18.     char *buf;
  19.     FILE *file;{
  20.     register char *p;
  21.     register struct macro *mp;
  22.     register struct linelink *lp;
  23.     register short dotlev;
  24.     CMDNUM ct;
  25.     short macnum;
  26.     char line[MAXIN];
  27.     CMDNUM comtyp();
  28.     char *strcpy();
  29.     char *malloc();
  30.     char *ngetl();
  31.     
  32.     skipnbl(buf);
  33.     skipbl(buf);
  34.     if(*buf == '\n'){
  35.         error("Missing macro name\n",CHARNULL);
  36.         return;
  37.         }
  38.     if(maccnt >= MAXMAC){
  39.         error("Too many macro definitions",CHARNULL);
  40.         return;
  41.         }
  42.     mp = ¯os[maccnt];
  43.     p = mp->macnam;
  44.     if((ct = comtyp(buf - 1,&macnum)) != UNKNOWN && ct != MAC)
  45.         builtins[(int)ct].notredefd = NO;
  46.     *p++ = *buf++;    /* record name */
  47.     *p++ = *buf++;
  48.     *p = '\0';
  49.     for(lp = mp->macend; lp != NULL; lp = lp->lastline, free(lp))
  50.         free(lp->lineptr);
  51.     mp->macend = NULL;
  52.     dotlev = 1;
  53.     do{
  54.         if((p = ngetl(line,file)) == CHARNULL)
  55.             break;    /* unexpected EOF */
  56.         ++fileline;
  57.         if(*p++ == env.comchr){
  58.             if(*p == '.')
  59.                 dotlev--;
  60.             else if(comtyp(line,&macnum) == DFN)
  61.                 dotlev++;    /* included .de */
  62.             }
  63.         if(dotlev > 0){
  64.             if((lp = (struct linelink *)malloc(sizeof(struct linelink))) == NULL){
  65.                 error(nomem,CHARNULL);
  66.                 break;
  67.                 }
  68.             lp->lastline = mp->macend;
  69.             mp->macend = lp;
  70.             if((lp->lineptr = malloc((unsigned)(strlen(line) + 1))) == NULL){
  71.                 error(nomem,CHARNULL);
  72.                 break;
  73.                 }
  74.             strcpy(lp->lineptr,line);
  75.             }
  76.         }while(dotlev > 0);
  77.     maccnt++;
  78. }
  79.  
  80. /*
  81. **    getseg - puts out part of header
  82. */
  83. char *getseg(buf,copy,copyend,term,pageno)
  84.     char *buf,*copy,*copyend,term;
  85.     short pageno;{
  86.     register short i;
  87.     register char *p;
  88.     short itorom(),itoeng();
  89.     
  90.     p = buf;
  91.     for( ;copy != copyend && *p != term && *p != '\0' && *p != '\n'; p++){
  92.         if(*p == PAGENUM){
  93.             switch(env.numtyp){
  94.                 case ARABIC:
  95.                 sprintf(copy, "%d", pageno);
  96.                 i = strlen(copy);
  97.                 break;
  98.                 case ROMAN:
  99.                 i = itorom(pageno,copy,min(MAXCHARS,(short)(copyend - copy)));
  100.                 break;
  101.                 case ENGLISH:
  102.                 i = itoeng(pageno,copy,copyend);
  103.                 break;
  104.                 }
  105.             copy += i;
  106.             }
  107.         else
  108.             *copy++ = *p;
  109.         }
  110.     if(*p == term)
  111.         p++;
  112.     *copy = '\0';
  113.     return(p);
  114. }
  115.  
  116. /*
  117. **    gettl - copy title from buf to ttl
  118. */
  119. char *gettl(buf)
  120.     char *buf;{
  121.     register char *p,*q;
  122.     char *strcpy();
  123.     char *malloc();
  124.     
  125.     p = buf;
  126.     skipnbl(p);
  127.     skipbl(p);    /* find argument */
  128.     if((q = malloc((unsigned)(strlen(p) + 1))) == NULL){
  129.         error(nomem,CHARNULL);
  130.         return(q);
  131.         }
  132.     strcpy(q,p);
  133.     return(q);
  134. }
  135.  
  136. /*
  137. **    getval - evaluate optional numeric argument
  138. */
  139. short getval(buf,argtyp)
  140.     char *buf;
  141.     char *argtyp;{
  142.     int atoi();
  143.     
  144.     skipnbl(buf);
  145.     skipbl(buf);    /* find argument */
  146.     *argtyp = *buf;
  147.     if(!isdigit(*buf))
  148.         buf++;
  149.     return(atoi(buf));
  150. }
  151.  
  152. /*
  153. **    getwrd - get a non - blank word from instr(i) to out, increment i
  154. */
  155. char *getwrd(instr,out)
  156.     char *instr,*out;{
  157.     register char c;
  158.     register char *p,*q;
  159.     
  160.     p = instr;
  161.     q = out;
  162.     while((*p == ' ' || *p == '\t') && *p != env.tabchr)
  163.         p++;
  164.     instr = p;
  165.     if(*p == env.tabchr)
  166.         *q++ = *p;
  167.     else{
  168.         while((c = *p) != '\0' && c != ' ' && c != '\t'
  169.             && c != '\n' && c != env.tabchr){
  170.             *q++ = *p++;
  171.             }
  172.         }
  173.     *q = '\0';
  174.     return(p == instr ? NULL : p);
  175. }
  176.  
  177. /*
  178. **    itorom - converts integer to roman numerals
  179. */
  180. short itorom(num,str,flen)
  181.     char *str;
  182.     short num,flen;{
  183.     register short i,j;
  184.     char *p;
  185.     static short romval[]    = { 1000,500,100,50,10,5,1,0 };
  186.     static short reltab[]    = { 2,1,2,1,2,1,1,0 };
  187.     static char romlet[]    = "mdclxvi0";
  188.     
  189.     p = str;
  190.     if(num < 0 && flen > 1){
  191.         num = -num;
  192.         *p++ = '-';
  193.         }
  194.     for(i = 0; num > 0; i++){
  195.         while(num >= romval[i]){
  196.             num -= romval[i];
  197.             *p++ = romlet[i];
  198.             }
  199.         j = i + reltab[i];
  200.         if(num >= (romval[i] - romval[j])){
  201.             num -= (romval[i] - romval[j]);
  202.             *p++ = romlet[j];
  203.             *p++ = romlet[i];
  204.             }
  205.         }
  206.     *p = '\0';
  207.     return((short)(p - str));
  208. }
  209.  
  210. /*
  211. **    leadbl - delete leading blanks, set tival
  212. */
  213. leadbl(buf)
  214.     char *buf;{
  215.     register char *p;
  216.     
  217.     linebreak();
  218.     p = buf;
  219.     skipnbl(buf);
  220.     if(*buf != '\n')
  221.         env.tival = (buf - p);
  222.     while(*buf != '\0')        /* move line to left */
  223.         *p++ = *buf++;
  224.     *p = '\0';
  225. }
  226.  
  227. /*
  228. **    newpage - put out as many blank pages as necessary to satisfy
  229. **    reserved page count 'respage'
  230. */
  231. newpage(){
  232.  
  233.     phead();
  234.     for( ; respage > 0; respage--){
  235.         skip(env.bottom + 1 - lineno);
  236.         pfoot();
  237.         phead();
  238.         }
  239. }
  240.  
  241. /*
  242. **    nextline - predicts the next line after n
  243. */
  244. short nextline(n)
  245.     register short n;{
  246.     register short i;
  247.  
  248.     i = n + 1;
  249.     if(i > env.bottom)
  250.         i = env.m1val + env.m2val + 1;
  251.     return(i);
  252. }
  253.  
  254. /*
  255. **    nextab - returns position of next tab stop
  256. */
  257. short nextab(pos)
  258.     short pos;{
  259.     register short i,k;
  260.     
  261.     for(i =  0; i < MAXTABS; i++){
  262.            if(env.tabpos[i] == 0)
  263.             break;
  264.            if(env.tabpos[i] > pos){
  265.                    k = env.tabpos[i];
  266.                    return(k);
  267.                    }
  268.            }
  269.     k = pos + 1;
  270.     return(k);
  271. }
  272.  
  273. /*
  274. **    ngetl - gets line from input or pushback buffer
  275. */
  276. char *ngetl(buf,file)
  277.     char *buf;
  278.     FILE *file;{
  279.     char *fgets();
  280.     char *strcpy();
  281.     
  282.     if(pblev <= 0)
  283.         return(fgets(buf,MAXIN,file));
  284.     else{
  285.         pblev--;
  286.         strcpy(buf,pbptr[pblev]);
  287.         }
  288.     return(buf);
  289. }
  290.  
  291. /*
  292. **    pfoot - put out page footer
  293. */
  294. pfoot(){
  295.     
  296.     skip(env.m3val);
  297.     if(env.m4val > 0){
  298.         puttl(curpag % 2 ? env.oddftr : env.evenftr, curpag);
  299.         skip(env.m4val - 1);
  300.         }
  301. }
  302.  
  303. /*
  304. **    phead - put out page header
  305. */
  306. phead(){
  307.     short nextline();
  308.     
  309.     curpag = newpag;
  310.     newpag++;
  311.     if(ttyfd >= 0 && pausecount-- <= 0){
  312.         fflush(stdout);
  313.         waitfornl();
  314.         pausecount = pages - 1;
  315.         }
  316.     if(trapmac[0] != '\0')
  317.         springtrap();
  318.     if(env.m1val > 0){
  319.         skip(env.m1val - 1);
  320.         puttl(curpag % 2 ? env.oddhdr : env.evenhdr, curpag);
  321.         }
  322.     skip(env.m2val);
  323.     lineno = env.m1val + env.m2val + 1;
  324.     peekno = nextline(lineno);
  325. }
  326.  
  327. /*
  328. **    pushback - pushback line onto input
  329. */
  330. pushback(buf)
  331.     char *buf;{
  332.  
  333.     if(pblev > MAXPB){
  334.         error("Not enough pushback space\n",CHARNULL);
  335.         return;    /* to catch stack overflow */
  336.         }
  337.     pbptr[pblev] = buf;
  338.     pblev++;
  339. }
  340.  
  341. /*
  342. **    put - put out line with proper spacing and indenting
  343. */
  344. put(buf)
  345.     char *buf;{
  346.     short nextab();
  347.     register char c;
  348.     register short col,i;
  349.     short nextline();
  350.     
  351.     if(lineno == 0 || lineno > env.bottom)
  352.         newpage();
  353.     for(i = (env.tival + env.poval); i--; )
  354.         putchar(' ');
  355.     col = env.tival;
  356.     env.tival = env.inval;
  357.     for(; (c = *buf) != '\0'; buf++){
  358.         if(c == env.ubchr)
  359.             c = ' ';    /* put blanks instead of blank replacement */
  360.         if(c == env.tabchr){
  361.             i = nextab(col);    /* nextab wants last used column */
  362.             for(; col < i; col++)
  363.                 putchar(' ');
  364.             continue;
  365.             }
  366.         else if(c == '\b')
  367.             col--;
  368.         else
  369.             col++;
  370.         putchar(c);
  371.         }
  372.     skip(min(env.lsval - 1,env.bottom - lineno));
  373.     lineno += env.lsval;
  374.     peekno = nextline(lineno);
  375.     if(lineno > env.bottom){
  376.         pfoot();
  377.         if(env.skpval > 0){
  378.             skpage(env.skpval);
  379.             env.skpval = 0;
  380.             }
  381.         }
  382. }
  383.  
  384. /*
  385. **    putdir - output a directive
  386. */
  387. putdir(buf)
  388.     char *buf;{
  389.  
  390.     fprintf(stderr,"%.10s",buf);    /* first 10 chars */
  391. }
  392.  
  393. /*
  394. **    puttl - put out title line with optional page number
  395. */
  396. puttl(buf,pageno)
  397.     char *buf;
  398.     short pageno;{
  399.     register char *p,*q;
  400.     register short col,newcol;
  401.     char copy[MAXOUT],term;
  402.     short width();
  403.     char *getseg();
  404.     
  405.     for(col = env.poval; col-- > 0; )
  406.         tputc(' ');
  407.     term = *buf;
  408.     if(term == '\n'){
  409.         tputc('\n');
  410.         return;
  411.         }
  412.     col = 0;
  413.     p = buf + 1;
  414.     p = getseg(p,copy,©[MAXOUT],term,pageno);
  415.     col += width(copy);
  416.     for(q = copy; *q != '\0'; q++)
  417.         tputc(*q);
  418.     p = getseg(p,copy,©[MAXOUT],term,pageno);
  419.     newcol = (env.llval - strlen(copy))/2;    /* start of centre */
  420.     for(; col < newcol; col++)
  421.         tputc(' ');
  422.     col += width(copy);
  423.     for(q = copy; *q != '\0'; q++)
  424.         tputc(*q);
  425.     p = getseg(p,copy,©[MAXOUT],term,pageno);
  426.     newcol = env.llval - strlen(copy);    /* start of right */
  427.     for(; col < newcol; col++)
  428.         tputc(' ');
  429.     for(q = copy; *q != '\0'; q++)
  430.         tputc(*q);
  431.     tputc('\n');
  432. }
  433.  
  434. /*
  435. **    putwrd - put a word in outbuf; includes margin justification
  436. */
  437. putwrd(wrdbuf)
  438.     char *wrdbuf;{
  439.     char *strcpy();
  440.     register short l,w,lnval,nextra;
  441.     short width(), nextab();
  442.     int strlen();
  443.     
  444.     lnval = env.llval - env.tival;
  445.     if(*wrdbuf == env.tabchr){
  446.         outw = nextab(outw + env.tival) - env.tival;
  447.         /* because outw floats from the indent */
  448.         /* and nextab is absolute */
  449.         if(outp  != outbuf && outw > lnval){
  450.             linebreak();
  451.             outw = nextab(outw + env.tival) - env.tival;
  452.             }
  453.         *++outp = env.tabchr;
  454.         outwds = 0;        /* adjust from next word */
  455.         }
  456.     else{
  457.         w = width(wrdbuf);
  458.         l = strlen(wrdbuf);
  459.         if(outp != outbuf && (outw + w > lnval ||    /* too big */
  460.             (char *)(outp + l) >= &outbuf[MAXOUT])){
  461.             --outp;    /* we put in a blank earlier */
  462.             if(env.adjust == YES){
  463.                 nextra = lnval - outw + 1;
  464.                 spread(outp,nextra,outwds);
  465.                 outp += nextra;
  466.                 }
  467.             linebreak();        /* flush previous line */
  468.             }
  469.         strcpy(outp,wrdbuf);
  470.         outp += l;
  471.         *outp++ = ' ';        /* blank between words */
  472.         outw += w + 1;            /* 1 for blank */
  473.         outwds++;
  474.         }
  475. }
  476.  
  477. /*
  478. **    resenv - restore environment n levels back
  479. */
  480. resenv(n)
  481.     short n;{
  482.     register struct envir *ep,*tp;
  483.     
  484.     linebreak();        /* to flush any latent output */
  485.     for(ep = curenv; ep != NULL && --n > 0; free(tp))
  486.         ep = (tp = ep)->lastenv;
  487.     if(ep != NULL){
  488.         env = *ep;
  489.         curenv = ep->lastenv;
  490.         free(ep);
  491.         }
  492. }
  493.  
  494. /*
  495. **    savenv - keep environment for later restoration
  496. */
  497. savenv(){
  498.     register struct envir *ep;
  499.     char *malloc();
  500.     
  501.     if((ep = (struct envir *)malloc(sizeof(env))) == NULL){
  502.         error(nomem,CHARNULL);
  503.         return;
  504.         }
  505.     *ep = env;    /* structure copy */
  506.     ep->lastenv = curenv;
  507.     curenv = ep;
  508. }
  509.  
  510. /*
  511. **    set - set parameter and check range
  512. */
  513. short set(param,val,argtyp,defval,minval,maxval)
  514.     short param,val,defval,minval,maxval;
  515.     char argtyp;{
  516.     
  517.     switch(argtyp){
  518.         case '\n':
  519.             param = defval;
  520.             break;
  521.         case '+':
  522.             param = param + val;
  523.             break;
  524.         case '-':
  525.             param = param - val;
  526.             break;
  527.         default:
  528.             param = val;
  529.         }
  530.     param = min(param,maxval);
  531.     param = max(param,minval);
  532.     return(param);
  533. }
  534.  
  535. /*
  536. **    settrap - record macro name to be invoked on page crossing
  537. */
  538. settrap(buf)
  539.     char *buf;{
  540.     register char *p;
  541.  
  542.     p = buf;
  543.     skipnbl(p);
  544.     skipbl(p);
  545.     if(*p == '\n'){
  546.         trapmac[0] = '\0';
  547.         return;
  548.         }
  549.     trapmac[0] = *p++;
  550.     trapmac[1] = *p;
  551. }
  552.  
  553. /*
  554. **    skip - output n blank lines
  555. */
  556. skip(n)
  557.     short n;{
  558.     
  559.     while(n-- > 0)
  560.         putchar('\n');
  561. }
  562.  
  563. /*
  564. **    skpage - skip n pages
  565. */
  566. skpage(n)
  567.     short n;{
  568.     short nextline();
  569.     
  570.     while(n-- > 0){
  571.         newpage();
  572.         skip(env.bottom + 1 - lineno);
  573.         lineno = env.bottom + 1;
  574.         peekno = nextline(lineno);
  575.         pfoot();
  576.         }
  577. }
  578.  
  579. /*
  580. **    spc - space n lines or to bottom of page (cf blnk)
  581. */
  582. spc(n)
  583.     short n;{
  584.     short nextline();
  585.     
  586.     linebreak();
  587.     if(lineno > env.bottom)
  588.         return;
  589.     if(lineno == 0)
  590.         newpage();
  591.     skip(min(n,env.bottom + 1 - lineno));
  592.     lineno += n;
  593.     peekno = nextline(lineno);
  594.     if(lineno > env.bottom){
  595.         pfoot();
  596.         if(env.skpval > 0){
  597.             skpage(env.skpval);
  598.             env.skpval = 0;
  599.             }
  600.         }
  601. }
  602.  
  603. /*
  604. **    spread - spread words to justify right margin
  605. */
  606. spread(ptr,nextra,nwrds)
  607.     char *ptr;
  608.     short nextra,nwrds;{
  609.     register char *p,*q;
  610.     register short nb,nholes;
  611.     static short dir    = 0;
  612.     
  613.     if(nextra <= 0 || nwrds <= 1)
  614.         return;
  615.     dir = !dir;        /* reverse previous direction */
  616.     nholes = nwrds - 1;
  617.     p = ptr - 1;
  618.     q = ptr + nextra;
  619.     *q-- = '\0';
  620.     while(p < q){
  621.         if((*q = *p) == ' '){
  622.             nb = dir ? (nextra - 1) / nholes + 1 :
  623.                 nextra / nholes;
  624.             nextra -= nb;
  625.             nholes--;
  626.             while(nb-- > 0){
  627.                 *--q = ' ';
  628.                 }
  629.             }
  630.         p--;
  631.         q--;
  632.         }
  633. }
  634.  
  635. /*
  636. **    springtrap - invoke macro on page crossing
  637. */
  638. springtrap(){
  639.     static char mac[5]    = ".xx\n";
  640.  
  641.     mac[1] = trapmac[0];
  642.     mac[2] = trapmac[1];
  643.     trapmac[0] = '\0';    /* deactivate trap */
  644.     pushback(mac);
  645. }
  646.  
  647. /*
  648. **    tabcol - enters pseudotab stops, checking validity
  649. */
  650. tabcol(buf)
  651.     char *buf;{
  652.     int atoi();
  653.     register short tp,incr,val;
  654.     
  655.     for(tp = 0; tp < MAXTABS - 1; tp++){
  656.         skipnbl(buf);
  657.         skipbl(buf);
  658.         if(*buf == '\n')
  659.             break;    /* end of list */
  660.         incr = *buf++ == '+' ? YES : NO;
  661.         val = atoi(buf);
  662.         if(incr == YES && tp > 1)    /* relative tab */
  663.             val = env.tabpos[tp - 1] + val;
  664.         env.tabpos[tp] = val;
  665.         if(val < 0 || (tp > 1 && val < env.tabpos[tp - 1]))
  666.             tp--;
  667.         }
  668.     env.tabpos[tp] = 0;    /* end of list */
  669. }
  670.  
  671. /*
  672. **    text - process text lines
  673. */
  674. text(inbuf)
  675.     char *inbuf;{
  676.     register char *p;
  677.     char wrdbuf[MAXIN];
  678.     char *getwrd();
  679.     
  680.     if(indline > 0){
  681.         fprintf(indfp,"%d. %s",curpag,inbuf);
  682.         indline--;
  683.         }
  684.     if(env.litval > 0){
  685.         put(inbuf);
  686.         env.litval--;
  687.         return;
  688.         }
  689.     if(*inbuf == ' ' || *inbuf == '\n')
  690.         leadbl(inbuf);    /* move left, set tival */
  691.     if(env.ulval > 0){            /* underlining */
  692.         underl(inbuf,wrdbuf,&wrdbuf[MAXIN]);
  693.         env.ulval--;
  694.         }
  695.     if(env.bdval > 0){
  696.         bold(inbuf,wrdbuf,&wrdbuf[MAXIN]);
  697.         env.bdval--;
  698.         }
  699.     if(env.ceval > 0){            /* centering */
  700.         center(inbuf);
  701.         put(inbuf);
  702.         env.ceval--;
  703.         }
  704.     else if(*inbuf == '\n')    /* all blank line */
  705.         put(inbuf);
  706.     else if(env.fill == NO)        /* unfilled text */
  707.         put(inbuf);
  708.     else
  709.         for(p = inbuf; (p = getwrd(p,wrdbuf)) != NULL;)
  710.             putwrd(wrdbuf);
  711. }
  712.  
  713. /*
  714. **    tputc  - intelligent filter routine to eliminate unnecessary blanks
  715. */
  716. tputc(c)
  717.     register char c;{
  718.     static short curcol    = 0;
  719.     static short lastcol    = 0;
  720.  
  721.     switch(c){
  722.         case ' ':
  723.         curcol++;
  724.         break;
  725.         case '\n':
  726.         curcol = lastcol = 0;
  727.         putchar(c);
  728.         break;
  729.         default:
  730.         while(lastcol++ < curcol)
  731.             putchar(' ');
  732.         putchar(c);
  733.         curcol++;
  734.         break;
  735.         }
  736. }
  737.  
  738. /*
  739. **    underl - underline a line
  740. */
  741. underl(buf,tbuf,tend)
  742.     char *buf,*tbuf,*tend;{
  743.     register char c;
  744.     register char *p,*q;
  745.     char *strcpy();
  746.     
  747.     p = buf;
  748.     q = tbuf;
  749.     while(*p != '\n' && q < tend){
  750.         if(isalnum(c = *p++)){
  751.             *q++ = '_';
  752.             *q++ = '\b';
  753.             }
  754.         *q++ = c;
  755.         }
  756.     *q++ = '\n';
  757.     *q = '\0';
  758.     strcpy(buf,tbuf);    /* copy it back to buf */
  759. }
  760.  
  761. /*
  762. **    waitfornl - crude version to get newline from terminal
  763. */
  764. waitfornl(){
  765.     char c;
  766.     int read();
  767.  
  768.     while(read(ttyfd,&c,1) > 0)
  769.         if(c == '\n')
  770.             break;
  771. }
  772.  
  773.  
  774. /*
  775. **    width - compute width of character string
  776. */
  777. short width(buf)
  778.     char *buf;{
  779.     register short i;
  780.     register char c;
  781.     
  782.     for(i = 0; (c = *buf) != '\0'; buf++){
  783.         if(c == '\b')
  784.             i--;
  785.         else if(c != '\n')
  786.             i++;
  787.         }
  788.     return(i);
  789. }
  790.